<?php
/*********************************************************************\
*  Copyright (c) 2007-2015, TH. All Rights Reserved.
*  Author :li
*  FName  :ApiTest.php
*  Time   :2019/11/05 08:56:58
*  Remark :测试请求的api小工具
\*********************************************************************/
// error_reporting(E_ALL);
FLEA::loadFile('FLEA_Helper_Array.php');
class Api_ApiTest extends FLEA_Controller_Action {
    function __construct() {
        $this->apiConfigDir = "Config/api/";
        $this->_class = __CLASS__;
    }

    /**
     * 测试的入口
     * Time：2019/11/05 09:09:14
     * @author li
     * @param 参数类型
     * @return 返回值类型
    */
    function test(){
        $this->configFileRes($this->apiConfigDir);

        //生成接口请求的页面
        if(isset($_GET['formPage']) && $_GET['formPage']){
            $this->apiPageBuild($_GET['formPage']);
            exit;
        }

        //处理接口的测试数据
        if(isset($_GET['type']) && $_GET['type'] == 'request'){
            $this->apitester();
            exit;
        }

        //处理掉token等参数，防止泄露
        foreach ($this->testApi as $key => & $v) {
            unset($this->testApi[$key]['CERTI_KEY']);
            unset($this->testApi[$key]['GEN_SIGN']);
            unset($this->testApi[$key]['configFile']);
        }

        // dump($this->testApi);
        // $modelKind = FLEA::getSingleton('Model_Jichu_ProKind');
        // $proKinds = $modelKind->findAll();
        $smarty = & $this->_getView();
        $smarty->assign('title','接口测试');
        $smarty->assign('Apis',$this->testApi);
        $smarty->display('Api/Test.tpl');

    }

    //响应接口的请求
    function apiPageBuild($formParams){
        list($index ,$keyApi) = explode(',' ,$formParams);
        $apiConfig = $this->testApi[$index];
        $curApi = $apiConfig['api_array'][$keyApi];
        $row['_API_KEY_'] = $formParams;

        //获取配置文件的版本号信息
        $file = pathinfo($apiConfig['configFile']);
        list($p ,$version) = explode('.', $file['filename']);
        $url = $this->imageUploadUrl($apiConfig ,$version);
        // dump($url);exit;

        if(!isset($curApi['params'])){
            echo "没有配置接口的params参数信息";exit;
        }

        //组织需要的页面数据
        $formItems = array();
        foreach ($curApi['params'] as $key => & $v) {
            if(is_string($v)){
                $v = array(
                    'title' =>$v,
                    'type'  =>'textarea',
                );
            }

            if($v['type'] == 'json'){
                $v['type'] = 'textarea';
            }

            $_tmp = array(
                'type'      =>'comp-'.$v['type'],
                'name'      =>$key,
                'title'     =>$v['title'],
                'clearable' =>true,
                'value'     =>'',
            );
            //图片的类型
            if($v['type'] == 'image'){
                $_tmp = array(
                    'type'         =>'comp-image',
                    'name'         =>$key,
                    'title'        =>$v['title'],
                    'action'       =>$url,//上传地址
                    'actionRemove' =>'',//删除图片时需要从服务器删除,可以不定义
                    'accept'       =>'.jpg,.png',//接受上传的文件类型
                    'limit'        =>$v['limit'] ? $v['limit'] : 1,//最大允许上传个数
                    'multiple'     =>true,//是否允许多选,
                );
            }
            // //文件类型
            // if($v['type'] == 'file'){
            //     $_tmp = array(
            //         'type'       =>'comp-file',
            //         'name'       =>$key,
            //         'title'      =>$v['title'],
            //         'buttonText' =>'开始上传附件',
            //         'action'     =>url('Test','ImportFileData'),//上传地址
            //         'accept'     =>'',//接受上传的文件类型.csv,jpg
            //         'limit'      =>$v['limit'] ? $v['limit'] : 1,//最大允许上传个数
            //         'value'      =>'',
            //     );
            // }

            $formItems[] = $_tmp;

            //提供默认值
            $row[$key] = isset($v['value']) ? $v['value'] : '';
        }
        // dump($row);
        $requestUrl = detect_uri_base()."?type=request";

        $smarty = & $this->_getView();

        $smarty->assign('formItems',$formItems);
        $smarty->assign('rules',array());
        $smarty->assign('title','接口基本信息');
        $smarty->assign('row',$row);
        $smarty->assign('action',$requestUrl);
        $smarty->display('Api/Form.tpl');
    }

    //图片上传的Url,form提交版
    function imageUploadUrl($apiConfig ,$version){
        $baseurl = detect_uri_base();
        $url = substr($baseurl, 0,strrpos($baseurl, '/') + 1).'api.php';
        //上传需要的参数
        $uploadParams = array(
            'method'    =>'image.file.upload',
            'version'   =>$version,
            'test'      =>'yes',
            'timestamp' =>time(),
        );
        $uploadParams['sign'] = $this->getSign($uploadParams ,$apiConfig['CERTI_KEY'] ,$apiConfig['GEN_SIGN']);
        $url.="?".http_build_query($uploadParams);
        return $url;
    }

    //处理接口的数据，调用接口
    function apitester(){
        $requestParam = file_get_contents('php://input');
        $post = json_decode($requestParam,true);

        list($index ,$key) = explode(',' ,$post['_API_KEY_']);
        $apiConfig = $this->testApi[$index];
        $curApi = $apiConfig['api_array'][$key];

        //处理文件，获取到对应的version
        $file = pathinfo($apiConfig['configFile']);
        list($p ,$version) = explode('.', $file['filename']);

        //循环确认参数类型
        foreach ($curApi['params'] as $k => & $v) {
            if(strtolower($v['type']) == 'json'){
                $post[$k] = json_decode($post[$k] ,1) ? json_encode(json_decode($post[$k] ,1)) : $post[$k];
            }

            //处理type为image的，这里默认只传递imageId，如果需要传整个对象，参数中定义object='true'
            if(strtolower($v['type']) == 'image' && !$v['object']){
                $post[$k] = join(',' , array_col_values($post[$k] ,'imageId'));
            }
        }
        // dump($post);
        //其他信息
        $post['method']    = $key;
        $post['version']   = $version;
        $post['timestamp'] = time();
        unset($post['_API_KEY_']);

        $post['sign'] = $this->getSign($post ,$apiConfig['CERTI_KEY'] ,$apiConfig['GEN_SIGN']);

        // dump($post);
        $baseurl = detect_uri_base();
        $url = substr($baseurl, 0,strrpos($baseurl, '/') + 1).'api.php';

        $timeR1 = microtime_float();
        $response = $this->requestPost($post ,$url ,$errorCode);
        $timeR2 = microtime_float();
        //响应的内容
        $response = json_decode($response ,1) ? json_decode($response ,1) : array('error'=>$response);

        echo json_encode(array('response'=>$response,'time'=>($timeR2 - $timeR1)));
        exit;
    }

    /**
     * 获取指定目录下的所有php文件
     * Time：2019/11/05 08:58:19
     * @author li
     * @param 参数类型
     * @return 返回值类型
    */
    function configFileRes($dir){
        $testApi = array();
        if (is_dir($dir)){
            if ($dh = opendir($dir)){
                while (($file = readdir($dh))!= false){
                    //文件名的全路径 包含文件名
                    $filePath = $dir.$file;
                    $fileInfo = pathinfo($filePath);
                    if(strtolower($fileInfo['extension']) == 'php'){
                        //初始化值，如果定义了则覆盖
                        $CERTI_KEY = "";
                        $GEN_SIGN = "";
                        $API_TITLE = "";
                        $api_array = array();
                        include($filePath);
                        if(count($api_array) > 0){
                            $testApi[] = array(
                                'configFile' =>$filePath,
                                'API_TITLE'  =>$API_TITLE ? $API_TITLE : $file,
                                'CERTI_KEY'  =>$CERTI_KEY,
                                'GEN_SIGN'   =>$GEN_SIGN,
                                'api_array'  =>$api_array,
                            );
                        }
                    }
                }
            }
            closedir($dh);
        }

        $this->testApi = $testApi;
        // dump($this->testApi);
    }

    public function requestPost($data, $url ,&$errorCode){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_URL,$url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        //设置cURL 参数，要求结果保存到字符串中还是输出到屏幕上, 0为直接输出屏幕，非0则不输出
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        //为了支持cookie
        //curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');

        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
        //curl_excc会输出内容，而$result只是状态标记
        $response = curl_exec($ch);
        $errorCode = curl_errno($ch);
        //释放curl句柄
        curl_close($ch);

        if(0 !== $errorCode) {
            return false;
        }

        return $response;
    }

    //模拟常规的签名算法
    function getSign($params ,$token ,$fun_sign){
        $self_sign = '';
        if($token){
            //默认的加密方法
            if(!$fun_sign){
                $self_sign = $this->gen_sign($params ,$token);
            }else{
                //使用自定义的加密方法，自定义一个类，类中必须实现gen_sign入口函数，
                $class = FLEA::getSingleton($fun_sign);
                $self_sign = $class->gen_sign($params ,$token);
            }
        }

        return $self_sign;
    }

    /**
     * 签名处理
     * Time：2017/04/26 09:02:38
     * @author li
    */
    private function gen_sign($params ,$certi_key){
        $str_key_value = $this->assemble($params);
        return strtoupper(md5(strtoupper(md5($str_key_value)).$certi_key));
    }

    /**
     * 字符串处理
     * Time：2017/04/26 09:02:38
     * @author li
    */
    private function assemble($params)
    {
        if(!is_array($params))  return null;
        ksort($params, SORT_STRING);
        $sign = '';
        foreach($params AS $key=>$val){
            if(is_null($val))   continue;
            if(is_bool($val))   $val = ($val) ? 'true' : 'false';
            $sign .= $key . (is_array($val) ? $this->assemble($val) : $val);
        }
        return $sign;
    }
}

?>